package com.example.androidstudy.ui.know

import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.text.TextUtils
import android.util.AttributeSet
import android.util.Log
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient


class MarkdownWebView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    defStyleRes: Int = 0
) :
    WebView(context, attrs, defStyleAttr, defStyleRes) {
    var mText: String? = null
    private var mWebViewLoaded = false

    init {
        init(context)
    }

    fun init(context: Context) {
        run {
            this.setBackgroundColor(Color.TRANSPARENT)

            // be careful, we do not need internet access
            this.settings.blockNetworkLoads = true

            //
            this.settings.loadWithOverviewMode = true
            this.settings.javaScriptEnabled = true
        }
        if (false) {
            // caching
            val dir = context.cacheDir
            if (!dir.exists()) {
                Log.d(TAG, "directory does not exist")
                val mkdirsStatus = dir.mkdirs()
                if (!mkdirsStatus) {
                    Log.e(TAG, "directory creation failed")
                }
            }
//            settings.setAppCachePath(dir.path)
//            settings.setAppCacheEnabled(true)
            settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
        }
        run {
            this.mWebViewLoaded = false
            this.webViewClient = object : WebViewClient() {
                override fun onPageFinished(view: WebView, url: String) {
                    super.onPageFinished(view, url)
                    if (mWebViewLoaded) {
                        // WebView was already finished
                        // do not load content again
                        return
                    }
                    mWebViewLoaded = true
                    if (!TextUtils.isEmpty(mText)) {
                        setText(mText)
                    }
                }

                override fun shouldOverrideUrlLoading(
                    view: WebView,
                    request: WebResourceRequest
                ): Boolean {
                    val uri = request.url
                    val scheme = uri.scheme
                    if (scheme.equals("http", ignoreCase = true) || scheme.equals(
                            "https",
                            ignoreCase = true
                        )
                    ) {
                        open(view.context, uri)
                        return true
                    }
                    return super.shouldOverrideUrlLoading(view, request)
                }
            }
        }
        run { this.loadUrl(HTML_LOCATION) }
    }

    fun setText(text: String?) {
        mText = text

        //wait for WebView to finish loading
        if (!mWebViewLoaded) {
            return
        }
        val escapeText: String
        escapeText = if (text != null) {
            escape(text)
        } else {
            ""
        }
        val javascriptCommand = "javascript:setText(\'$escapeText\')"
        this.loadUrl(javascriptCommand)
    }

    companion object {
        private val TAG = MarkdownWebView::class.java.simpleName
        private const val HTML_LOCATION = "file:///android_asset/AndroidMarkdown.html"
        fun open(context: Context, uri: Uri?): Boolean {
            val launchFlags = (Intent.FLAG_ACTIVITY_NEW_TASK
                    or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
            val intent = Intent(Intent.ACTION_VIEW, uri)
            intent.flags = launchFlags
            try {
                context.startActivity(intent)
                return true
            } catch (e: Exception) {
            }
            return false
        }

        fun escape(s: String): String {
            val out = StringBuilder(s.length + 128)
            var i = 0
            val length = s.length
            while (i < length) {
                val c = s[i]
                when (c) {
                    '"', '\\', '/' -> out.append('\\').append(c)
                    '\t' -> out.append("\\t")
                    '\b' -> out.append("\\b")
                    '\n' -> out.append("\\n")
                    '\r' -> out.append("\\r")
//                    '\f' -> out.append("\\u000c")
                    else -> if (c.code <= 0x1F) {
                        out.append(String.format("\\u%04x", c.code))
                    } else {
                        out.append(c)
                    }
                }
                i++
            }
            return out.toString()
        }
    }
}